import random
from django.shortcuts import render,redirect


from api import serializer as api_serializer
from userauths.models import User,Profile
from api import models as api_models

from django.core.mail import EmailMultiAlternatives
from django.conf import settings
from django.template.loader import render_to_string
from decimal import Decimal

from rest_framework import generics,status
from rest_framework.permissions import AllowAny
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.response import Response

import stripe
import requests
stripe.api_key = settings.STRIPE_SECRET_KEY
# Create your views here.
PAYPAL_CLIENT_ID = settings.PAYPAL_CLIENT_ID
PAYPAL_SECRET_ID = settings.PAYPAL_SECRET_ID

#jwt视图
class MyTokenObtainPairView(TokenObtainPairView):
    #指定序列化器类
    serializer_class = api_serializer.MyTokenObtainPairSerializer

class RegisterView(generics.CreateAPIView):
    queryset = User.objects.all()
    permission_classes = [AllowAny]
    serializer_class = api_serializer.RegisterSerializer

def generate_random_otp(length=7):
    #生成7个随机数字符串
    otp = ''.join([str(random.randint(0,9)) for _ in range(length)])
    return otp

class PasswordResetEmailVerifyAPIView(generics.RetrieveAPIView):
    permission_classes = [AllowAny]
    serializer_class = api_serializer.UserSerializer

    #RetrieveAPIView的主要方法
    ##从 URL 中提取主键或唯一标识参数,
    # 根据该参数查询对应的模型实例,
    # 执行权限检查和对象级别的权限验证,
    # 返回查询到的对象
    def get_object(self):
        email = self.kwargs['email']

        user = User.objects.filter(email=email).first()

        if user:
            user.otp = generate_random_otp()

            #生成JWT令牌
            uuidb64 = user.pk
            refresh = RefreshToken.for_user(user)
            refresh_token = str(refresh.access_token)
            user.refresh_token = refresh_token
            user.save()
            link = f"http://localhost:5173/create-password/?otp={user.otp}&uuidb64={uuidb64}&refresh_token={refresh_token}"
            context = {
                "link":link,
                "username":user.username
            }
            subject = "Password Rest"
            text_body = render_to_string("email/password_reset.txt",context)
            html_body = render_to_string("email/password_reset.html",context)
            msg = EmailMultiAlternatives(
                subject=subject,
                from_email= settings.DEFAULT_FROM_EMAIL,
                to=[user.email],
                body = text_body
            )
            msg.attach_alternative(html_body,"text/html")
            msg.send()

            print(f"link===={link}")
        return user
    

class PasswordChangeAPIView(generics.CreateAPIView):
    permission_classes = [AllowAny]
    serializer_class = api_serializer.UserSerializer

    def create(self,request,*args,**kwargs):
        otp = request.data['otp']
        uuidb64 = request.data['uuidb64']
        password = request.data['password']

        user = User.objects.get(id=uuidb64,otp = otp)
        if user:
            user.set_password(password)
            user.otp = ""
            user.save()

            return Response({"message":"Password Changed Successfully"},status=status.HTTP_201_CREATED)
        else:
            return Response({"message":"User Does not Exists"},status=status.HTTP_404_NOT_FOUND)
        

class CategoryListAPIView(generics.ListAPIView):
    queryset = api_models.Category.objects.filter(active=True)
    serializer_class = api_serializer.CategorySerializer
    permission_classes = [AllowAny]

class CourseListAPIView(generics.ListAPIView):
    queryset = api_models.Course.objects.filter(platform_status="Published",teacher_course_status="Published")
    serializer_class = api_serializer.CourseSerializer
    permission_classes = [AllowAny]

#RetrieveAPIView用于检索单个模型实例，GET方法
#1.要么url中传入pk，2.要么lookup_field指明参数，3.要么重写get_object()
class CourseDetailAPIView(generics.RetrieveAPIView):
    serializer_class = api_serializer.CourseSerializer
    permission_classes = [AllowAny]
    queryset = api_models.Course.objects.filter(platform_status="Published",teacher_course_status="Published")

    def get_object(self):
        slug = self.kwargs['slug']
        course = api_models.Course.objects.get(slug=slug,platform_status="Published",teacher_course_status="Published")
        return course
    
#
class CartAPIView(generics.CreateAPIView):
    queryset = api_models.Cart.objects.all()
    serializer_class = api_serializer.CartSerializer
    permission_classes = [AllowAny]

    def create(self,request,*args,**kwargs):
        course_id = request.data['course_id']
        user_id = request.data['user_id']
        price = request.data['price']
        country_name = request.data['country_name']
        cart_id = request.data['cart_id']
        course = api_models.Course.objects.filter(id=course_id).first()

        if user_id != 'undefined':
            user = User.objects.filter(id=user_id).first()
        else:
            user = None

        try:
            country_object = api_models.Country.objects.filter(name=country_name).first()
            country = country_object.name
        except:
            country_object = None
            country = "China"

        if country_object:
            tax_rate = country_object.tax_rate / 100
        else:
            tax_rate = 0

        cart = api_models.Cart.objects.filter(cart_id=cart_id,course=course).first()

        if cart:
            cart.course = course
            cart.user = user
            cart.price = price
            cart.tax_fee = Decimal(tax_rate) * Decimal(price)
            cart.country = country
            cart.cart_id = cart_id
            cart.total = Decimal(cart.price) + Decimal(cart.tax_fee)
            cart.save()
            return Response({"message":"Cart Updated Successfully"},status=status.HTTP_200_OK)
        else:
            cart = api_models.Cart()

            cart.course = course
            cart.user = user
            cart.price = price
            cart.tax_fee = Decimal(tax_rate) * Decimal(price)
            cart.country = country
            cart.cart_id = cart_id
            cart.total = Decimal(cart.price) + Decimal(cart.tax_fee)
            cart.save()
            return Response({"message":"Cart Create Successfully"},status=status.HTTP_201_CREATED)
        
class CartListAPIView(generics.ListAPIView):
    serializer_class = api_serializer.CartSerializer
    permission_classes = [AllowAny]

    def get_queryset(self):
        cart_id = self.kwargs['cart_id']
        queryset = api_models.Cart.objects.filter(cart_id=cart_id)
        return queryset
    
class CartItemDeleteAPIView(generics.DestroyAPIView):
    serializer_class = api_serializer.CartSerializer
    permission_classes = [AllowAny]

    def get_object(self):
        cart_id = self.kwargs['cart_id']
        item_id = self.kwargs['item_id']
        return api_models.Cart.objects.filter(cart_id=cart_id,id=item_id).first()

class CartStatsAPIView(generics.RetrieveAPIView):
    serializer_class = api_serializer.CartSerializer
    permission_classes = [AllowAny]
    lookup_field = 'cart_id'

    def get_queryset(self):
        cart_id = self.kwargs['cart_id']
        queryset = api_models.Cart.objects.filter(cart_id=cart_id)
        return queryset
    
    def get(self,request,*args,**kwargs):
        queryset = self.get_queryset()

        total_price = 0.00
        total_tax = 0.00
        total_total = 0.00

        for cart_item in queryset:
            total_price += float(self.calculate_price(cart_item))
            total_tax += float(self.calculate_tax(cart_item))
            total_total += round(float(self.calculate_total(cart_item)),2)

        data = {
            "price":total_price,
            "tax":total_tax,
            "total":total_total
        }

        return Response(data)

    def calculate_price(self,cart_item):
        return cart_item.price
    
    def calculate_tax(self,cart_item):
        return cart_item.tax_fee
    
    def calculate_total(self,cart_item):
        return cart_item.total

class CreateOrderAPIView(generics.CreateAPIView):
    serializer_class = api_serializer.CartOrderSerializer
    permission_classes = [AllowAny]
    queryset = api_models.CartOrder.objects.all()

    def create(self,request,*args,**kwargs):
        full_name = request.data['full_name']
        email = request.data['email']
        country = request.data['country']
        cart_id = request.data['cart_id']
        user_id = request.data['user_id']

        if user_id != 0:
            user = User.objects.get(id=user_id)
        else:
            user = None

        cart_items = api_models.Cart.objects.filter(cart_id=cart_id)

        total_price = Decimal(0.00)
        total_tax = Decimal(0.00)
        total_initial_total = Decimal(0.00)
        total_total = Decimal(0.00)

        order = api_models.CartOrder.objects.create(
            full_name = full_name,
            email = email,
            country=country,
            student=user
        )

        for c in cart_items:
            api_models.CartOrderItem.objects.create(
                order = order,
                course = c.course,
                price = c.price,
                tax_fee = c.tax_fee,
                total = c.total,
                initial_total = c.total,
                teacher = c.course.teacher
            )

            total_price += Decimal(c.price)
            total_tax += Decimal(c.tax_fee)
            total_initial_total += Decimal(c.total)
            total_total += Decimal(c.total)

            order.teachers.add(c.course.teacher)

        order.sub_total = total_price
        order.tax_fee = total_tax
        order.initial_total = total_initial_total
        order.total = total_total
        order.save()

        return Response({"message":"Order Created Successfully",'order_oid':order.oid},status=status.HTTP_201_CREATED)
    
class CheckoutAPIView(generics.RetrieveAPIView):
    serializer_class = api_serializer.CartOrderSerializer
    permission_classes = [AllowAny]
    queryset = api_models.CartOrder.objects.all()
    lookup_field = 'oid'

class CouponApplyAPIView(generics.CreateAPIView):
    serializer_class = api_serializer.CouponSerializer
    permission_classes = [AllowAny]

    def create(self,request,*args,**kwargs):
        order_oid = request.data['order_oid']
        coupon_code = request.data['coupon_code']

        order = api_models.CartOrder.objects.get(oid=order_oid)
        coupon = api_models.Coupon.objects.get(code=coupon_code)

        if coupon:
            order_items = api_models.CartOrderItem.objects.filter(order=order,teacher=coupon.teacher)
            for oi in order_items:
                if not coupon in oi.coupons.all():
                    discount = oi.total * coupon.discount/100

                    oi.total -=discount
                    oi.price -= discount
                    oi.saved +=discount
                    oi.applied_coupon = True
                    oi.coupons.add(coupon)

                    order.coupons.add(coupon)
                    order.total -= discount
                    order.sub_total -= discount
                    order.saved += discount

                    oi.save()
                    order.save()
                    coupon.userd_by.add(order.student)
                    return Response({"message":"Coupon Found and Activated",'icon':'success'},status=status.HTTP_201_CREATED)
                else:
                    return Response({"message":"Coupon Already Applied",'icon':'warning'},status=status.HTTP_200_OK)
        else:
            return Response({"message":"Coupon Not Found",'icon':'error'},status=status.HTTP_404_NOT_FOUND)
        
class StripCheckoutAPIView(generics.CreateAPIView):
    serializer_class = api_serializer.CartOrderSerializer
    permission_classes = [AllowAny]

    def create(self,request,*args,**kwargs):
        order_oid = self.kwargs['order_oid']
        order = api_models.CartOrder.objects.get(oid=order_oid)

        if not order:
            return Response({"message":"Order not Found"},status=status.HTTP_404_NOT_FOUND)
        
        try:
            checkout_session = stripe.checkout.Session.create(
                customer_email = order.email,
                payment_method_types = ['card','alipay'],
                line_items=[
                    {
                        'price_data':{
                            'currency':'usd',
                            'product_data':{
                                'name':order.full_name,
                            },
                            'unit_amount':int(order.total*100)
                        },
                        'quantity':1
                    }
                ],
                mode='payment',
                success_url=settings.FRONTEND_SITE_URL + 'payment-success/'+order.oid+'?session_id={CHECKOUT_SESSION_ID}',
                cancel_url = settings.FRONTEND_SITE_URL + 'payment-failed'
            )
            order.stripe_session_id = checkout_session.id
            print(checkout_session)
            return redirect(checkout_session.url)
        except stripe.error.StripeError as e:
            return Response({"message":f"Something wrong.Error:{e}"})


def get_access_token(client_id,secret_key):
    token_url = "https://api.sandbox.paypal.com/v1/oauth/token"
    data = {'grant_type':'client_credentials'}
    auth = {client_id,secret_key}
    response = requests.post(token_url,data,auth)

    if response.status_code == 200:
        print("Access Token ===",response.json()['access_token'])
        return response.json()['access_token']
    else:
        raise Exception(f"Failed to get access token from paypal {response.status_code}")

class PaymentSuccessAPIView(generics.CreateAPIView):
    serializer_class = api_serializer.CartOrderSerializer
    permission_classes = [AllowAny]

    def create(self,request,*args,**kwargs):
        order_oid = request.data['order_oid']
        session_id = request.data['session_id']
        paypal_order_id = request.data['paypal_order_id']

        order = api_models.CartOrder.objects.get(oid=order_oid)
        order_items = api_models.CartOrderItem.objects.filter(order=order)

        if paypal_order_id != 'null':
            paypal_api_url = f'https://api-m.sandbox.paypal.com/v2/checkout/orders/{paypal_order_id}'
            headers = {
                'Content-Type':'application/json',
                'Authorization':f"Bearer {get_access_token(PAYPAL_CLIENT_ID,PAYPAL_CLIENT_ID)}"
            }

            response = requests.get(paypal_api_url,headers=headers)
            if response.status_code ==200:
                paypal_order_data = response.json()
                paypal_payment_status = paypal_order_data['status']
                if paypal_payment_status =='COMPLETED':
                    if order.payment_status =='Processing':
                        order.payment_status ='Paid'
                        order.save()
                        api_models.Notification.objects.create(user=order.student,order=order,type='Course Enrollment Completed')
                        for o in order_items:
                            api_models.Notification.objects.create(
                                teacher=o.teacher,
                                order=order,
                                order_item = o,
                                type='New order'
                            )
                            api_models.EnrolledCourse.objects.create(
                                course=o.course,
                                user=order.student,
                                teacher=o.teacher,
                                order_item=o
                            )
                        
                        return Response({'message':'Payment successfull'})
                    else:
                        return Response({"message":'You have already paid!'})
                else:
                    return Response({'message':'Payment not successful'})
            else:
                return Response({'message':'Paypal Error Occured'})
            
            if session_id != 'null':
                session = stripe.checkout.Session.retrieve(session_id)
                if session.payment_status == 'paid':
                    if order.payment_status == 'Processing':
                        order.payment_status ='Paid'
                        order.save()
                        api_models.Notification.objects.create(user=order.student,order=order,type='Course Enrollment Completed')
                        for o in order_items:
                            api_models.Notification.objects.create(
                                teacher=o.teacher,
                                order=order,
                                order_item = o,
                                type='New order'
                            )
                            api_models.EnrolledCourse.objects.create(
                                course=o.course,
                                user=order.student,
                                teacher=o.teacher,
                                order_item=o
                            )
                        return Response({'message':'Payment Successfull'})
                    else:
                        return Response({"message":'You have already paid!'})
                else:
                    return Response({'message':'Payment not successful'})
            
class SearchCourseAPIView(generics.ListAPIView):
    serializer_class = api_serializer.CourseSerializer
    permission_classes = [AllowAny]

    def get_queryset(self):
        query = self.request.GET.get('query')
        return api_models.Course.objects.filter(title__icontains=query,platform_status="Published",teacher_course_status="Published")
    





    